package com.jfinalnat.httpclient.sdk;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;

import com.jfinal.upload.MultipartRequest;
import com.jfinal.upload.UploadFile;
import com.jfinalnat.httpclient.processor.GetProcessor;

public class DefaultHttpProxy {
	
	private static final Log log = LogFactory.getLog(DefaultHttpProxy.class); 

	/** * 执行url请求 
	 * @param isUpload */ 
	public boolean execute(HttpServletRequest request, HttpServletResponse response) {
		
		String type = request.getContentType();
		
		if (type != null && type.contains("multipart/form-data")) {
			return executeFile(request, response);
		} else {
			return executeRequest(request, response);
		}
			
	}
	
	public boolean execute(HttpServletRequest request, HttpServletResponse response, String uri) {
		
		String type = request.getContentType();
		
		if (type != null && type.contains("multipart/form-data")) {
			return executeFile(request, response, uri);
		} else {
			return executeRequest(request, response, uri);
		}
			
		
	}
	
	private boolean executeRequest(HttpServletRequest request, HttpServletResponse response) { 
		
		long beforeTime = System.currentTimeMillis(); 
		// 根据request创建请求 
		GetProcessor getProcessor = new GetProcessor();
		HttpRequestBase httpRequest = getProcessor.doRequest(request); 
		if (httpRequest == null) { return false; } 
		// 从连接池中获得
		CloseableHttpClient httpClient = HttpClientFactory.getHttpClient(); 
		CloseableHttpResponse proxyRes = null; 
		OutputStream outputStream = null;
		try { 
			HttpClientContext httpContext = HttpClientContext.create(); 
			proxyRes = httpClient.execute(httpRequest, httpContext); 
			getProcessor.doResponse(response, proxyRes); 
			HttpEntity entity = proxyRes.getEntity(); 
			if (proxyRes.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 
				outputStream = response.getOutputStream(); 
				entity.writeTo(outputStream);
				outputStream.flush(); 
			} else { 
				response.sendError(proxyRes.getStatusLine().getStatusCode()); }
				long afterTime = System.currentTimeMillis(); 
				log.info("-----代理耗时["+(afterTime-beforeTime)+"ms]-----"); 
		} catch (IOException e) { 
			log.error("", e);
			return false; 
		} finally {
			try {
				if (proxyRes != null) proxyRes.close();
				if (outputStream != null) outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
	    }
		return true; 
		
	}
	
	private boolean executeFile(HttpServletRequest request, HttpServletResponse response) { 
		
		long beforeTime = System.currentTimeMillis(); 
		
		HttpPost httpPost = new HttpPost(PoolingHttpClientConfig.targetUrl+request.getRequestURI());
		
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(30000).setConnectTimeout(30000).build();
		httpPost.setConfig(requestConfig);
		
		//添加参数
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		Map<String, String[]> mapParas = request.getParameterMap();
		for (Entry<String, String[]> entry : mapParas.entrySet()) {
			for(String value : entry.getValue()) {				
				nvps.add(new BasicNameValuePair(entry.getKey(), value));
			}
		}
		
		try {
			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}
		
		//添加文件
		List<UploadFile> uploadFileList = new MultipartRequest(request).getFiles();
		
		MultipartEntityBuilder  multipartEntityBuilder = MultipartEntityBuilder.create();
		
		int i = 1;
		for (UploadFile uploadFile : uploadFileList) {			
			multipartEntityBuilder.addPart("media"+i, new FileBody(uploadFile.getFile(), ContentType.APPLICATION_OCTET_STREAM, uploadFile.getFile().getName()));
			i++;
		}
		
		httpPost.setEntity(multipartEntityBuilder.build());
		
		// 从连接池中获得
		CloseableHttpClient httpClient = HttpClientFactory.getHttpClient(); 
		CloseableHttpResponse proxyRes = null; 
		OutputStream outputStream = null;
		try { 
			HttpClientContext httpContext = HttpClientContext.create(); 
			proxyRes = httpClient.execute(httpPost, httpContext); 
			new GetProcessor().doResponse(response, proxyRes); 
			HttpEntity entity = proxyRes.getEntity(); 
			if (proxyRes.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 
				outputStream = response.getOutputStream(); 
				entity.writeTo(outputStream);
				outputStream.flush(); 
			} else { 
				response.sendError(proxyRes.getStatusLine().getStatusCode()); }
				long afterTime = System.currentTimeMillis(); 
				log.info("-----代理耗时["+(afterTime-beforeTime)+"ms]-----"); 
		} catch (IOException e) { 
			log.error("", e);
			return false; 
		} finally {
			try {
				if (proxyRes != null) proxyRes.close();
				if (outputStream != null) outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
	    }
		return true; 
		
	}
	
	private boolean executeRequest(HttpServletRequest request, HttpServletResponse response, String uri) { 
		
		long beforeTime = System.currentTimeMillis(); 
		// 根据request创建请求 
		GetProcessor getProcessor = new GetProcessor();
		HttpRequestBase httpRequest = getProcessor.doRequest(request, uri); 
		if (httpRequest == null) { return false; } 
		// 从连接池中获得
		CloseableHttpClient httpClient = HttpClientFactory.getHttpClient(); 
		CloseableHttpResponse proxyRes = null; 
		OutputStream outputStream = null;
		try { 
			HttpClientContext httpContext = HttpClientContext.create(); 
			proxyRes = httpClient.execute(httpRequest, httpContext); 
			getProcessor.doResponse(response, proxyRes); 
			HttpEntity entity = proxyRes.getEntity(); 
			if (proxyRes.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 
				outputStream = response.getOutputStream(); 
				entity.writeTo(outputStream);
				outputStream.flush(); 
			} else { 
				response.sendError(proxyRes.getStatusLine().getStatusCode()); }
				long afterTime = System.currentTimeMillis(); 
				log.info("-----代理耗时["+(afterTime-beforeTime)+"ms]-----"); 
		} catch (IOException e) { 
			log.error("", e);
			return false; 
		} finally {
			try {
				if (proxyRes != null) proxyRes.close();
				if (outputStream != null) outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
	    }
		return true; 
		
	}
	
	private boolean executeFile(HttpServletRequest request, HttpServletResponse response, String uri) { 
		
		long beforeTime = System.currentTimeMillis(); 
		
		HttpPost httpPost = new HttpPost(PoolingHttpClientConfig.targetUrl+(uri == null ? request.getRequestURI() : uri));
		
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(30000).setConnectTimeout(30000).build();
		httpPost.setConfig(requestConfig);
		
		//添加参数
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		Map<String, String[]> mapParas = request.getParameterMap();
		for (Entry<String, String[]> entry : mapParas.entrySet()) {
			for(String value : entry.getValue()) {				
				nvps.add(new BasicNameValuePair(entry.getKey(), value));
			}
		}
		
		try {
			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}
		
		//添加文件
		List<UploadFile> uploadFileList = new MultipartRequest(request).getFiles();
		
		MultipartEntityBuilder  multipartEntityBuilder = MultipartEntityBuilder.create();
		
		int i = 1;
		for (UploadFile uploadFile : uploadFileList) {			
			multipartEntityBuilder.addPart("media"+i, new FileBody(uploadFile.getFile(), ContentType.APPLICATION_OCTET_STREAM, uploadFile.getFile().getName()));
			i++;
		}
		
		httpPost.setEntity(multipartEntityBuilder.build());
		
		// 从连接池中获得
		CloseableHttpClient httpClient = HttpClientFactory.getHttpClient(); 
		CloseableHttpResponse proxyRes = null; 
		OutputStream outputStream = null;
		try { 
			HttpClientContext httpContext = HttpClientContext.create(); 
			proxyRes = httpClient.execute(httpPost, httpContext); 
			new GetProcessor().doResponse(response, proxyRes); 
			HttpEntity entity = proxyRes.getEntity();
			if (proxyRes.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 
				outputStream = response.getOutputStream(); 
				entity.writeTo(outputStream);
				outputStream.flush(); 
			} else { 
				response.sendError(proxyRes.getStatusLine().getStatusCode()); }
				long afterTime = System.currentTimeMillis(); 
				log.info("-----代理耗时["+(afterTime-beforeTime)+"ms]-----"); 
		} catch (IOException e) { 
			log.error("", e);
			return false; 
		} finally {
			try {
				if (proxyRes != null) proxyRes.close();
				if (outputStream != null) outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
	    }
		return true; 
		
	}
	
	
	/** * 执行url请求 返回json字符串 暂时不用 */ 
/*	public String execute(HttpServletRequest request, HttpServletResponse response) { 
		
		String json = "";
		
		long beforeTime = System.currentTimeMillis(); 
		// 根据request创建请求 
		GetProcessor getProcessor = new GetProcessor();
		HttpRequestBase httpRequest = getProcessor.doRequest(request); 
		if (httpRequest == null) { return null; } 
		// 从连接池中获得
		CloseableHttpClient httpClient = HttpClientFactory.getHttpClient(); 
		CloseableHttpResponse proxyRes = null; 
		try { 
			HttpClientContext httpContext = HttpClientContext.create(); 
			httpRequest.removeHeaders("Content-Length");
			proxyRes = httpClient.execute(httpRequest, httpContext); 
			//HttpServletResponse servletRes = response;
			//getProcessor.doResponse(servletRes, proxyRes); 
			HttpEntity entity = proxyRes.getEntity(); 
			if (proxyRes.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 
				json = entity != null ? EntityUtils.toString(entity) : proxyRes.getStatusLine().toString();
			} else { 
				json = proxyRes.getStatusLine().toString();
				//servletRes.sendError(proxyRes.getStatusLine().getStatusCode()); 
			}
			long afterTime = System.currentTimeMillis(); 
			log.info("-----代理耗时["+(afterTime-beforeTime)+"ms]-----"); 
		} catch (IOException e) {
			log.error("", e);
		}
		return json; 
		
	}*/
	
}
